﻿using System;
using System.Configuration;
using System.IO;
using System.Reflection;
using System.Windows;
using Core;
using Core.Infrastructure;
using Core.Interfaces;
using Core.IocHelpers;
using Core.Settings;
using log4net;
using Microsoft.Win32;
using TallyJ.Properties;
using TallyJ.Windows;
using SplashScreen=TallyJ.Windows.SplashScreen;

namespace TallyJ
{
  /// <summary>
  /// Interaction logic for App.xaml
  /// </summary>
  public partial class App
  {
    protected override void OnStartup(StartupEventArgs e)
    {
      base.OnStartup(e);

      // show the splash
      var about = new SplashScreen();
      about.Show();

      RegesterIoC();

      var log = IoC.Container.Resolve<ILog>();
      log.Info("Started");

      AbortIfWrongFrameworkVersion(log);

      LinkAppSettingsIntoCore();

      AskUserForDbPathIfNeeded();

      // StartPreparingNHibernate();

      AttachToCurrentData();

      var w = new Launch();
      w.Show();

      about.Close();
    }

    private void AttachToCurrentData()
    {
      var helper = IoC.Container.Resolve<IEnvironmentDataHelper>();
      helper.AttachToCurrentData();
    }

    private void StartPreparingNHibernate()
    {
      // start NHibernate startup processes on another thread
      var sessionProvider = IoC.Container.Resolve<ISessionProvider>();
      this.DispatcherAction(sessionProvider.PrepareSessionFactory);
    }

    private void AskUserForDbPathIfNeeded()
    {
      var dbFilePath = Settings.Default.DbFilePath;
      if (dbFilePath.HasNoContent() || !File.Exists(dbFilePath))
      {
        GetDbFilePath(true);
      }
    }

    private void AbortIfWrongFrameworkVersion(ILog log)
    {
      var frameworkTester = IoC.Container.Resolve<IFramework>();

      string message;
      if (!frameworkTester.IsVersion35(out message))
      {
        log.Info("Invalid framework: " + message);

        MessageBox.Show(
              message,
              "Unable to Execute", MessageBoxButton.OK, MessageBoxImage.Exclamation);

        Current.Shutdown();
      }
    }

    private void LinkAppSettingsIntoCore()
    {
      var coreAppSettings = IoC.Container.Resolve<IAppSettings>();
      coreAppSettings.LinkToSource(Settings.Default);
    }

    private void RegesterIoC()
    {
      AutoRegister.DoAutoRegistrations(IoC.Container); // local
      AutoRegister.DoAutoRegistrations(IoC.Container, Assembly.GetAssembly(typeof (IoC))); // core
      AutoRegister.DoAutoRegistrations(IoC.Container, Assembly.GetAssembly(typeof (DataXml.Extensions))); // core
      AutoRegister.DoAutoRegistrations(IoC.Container, Assembly.GetAssembly(typeof (DataMain.Extensions))); // core

      IoC.RegisterExternals();
      IoC.Container.RegisterType(typeof (ApplicationSettingsBase), typeof (Settings));
    }

    private void GetDbFilePath(bool shutdownOnCancel)
    {
      var fileDialog = new OpenFileDialog
                         {
                               CheckFileExists = false,
                               CheckPathExists = true,
                               DefaultExt = ".db",
                               Title = "Select existing data file, or specify the name for a new file",
                               FileName = "Community",
                               Multiselect = false,
                               InitialDirectory =
                                     Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                                                  "TallyJ"),
                               ValidateNames = true,
                               DereferenceLinks = true,
                               AddExtension = true,
                               Filter = "SQLite Data (.db)|*.db"
                         };
      var result = fileDialog.ShowDialog();
      if (result.Value)
      {
        // clicked okay
        var dbFilePath = fileDialog.FileName;
        if (dbFilePath.HasNoContent() || !Directory.Exists(Path.GetDirectoryName(dbFilePath)))
        {
          MessageBox.Show("Can't find that file or folder.");
          GetDbFilePath(shutdownOnCancel);
        }
        else
        {
          Settings.Default.DbFilePath = dbFilePath;
          Settings.Default.Save();
        }
      }
      else
      {
        if (shutdownOnCancel)
        {
          // cancelled
          Current.Shutdown();
        }
      }
    }
  }
}